﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Windows.Media;
using CommonBehaviors.Actions;
using DayWalker.Settings;
using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.Pathing;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Action = Styx.TreeSharp.Action;

namespace DayWalker.Helpers
{
   
    public static partial  class Helper
    {
        
        #region Attackable

        public static bool Attackable(WoWUnit target, int range)
        {
            if (target == null ||
                !target.IsValid ||
                !target.Attackable ||
                !target.CanSelect ||
                !target.IsAlive ||
                //target.IsCritter ||
                //Blacklist.Contains(target.Guid, BlacklistFlags.All) ||
                GetDistance(target) > range ||
                Invulnerable(target) ||
                DebuffCCBreakonDamage(target) ||
                !IsEnemy(target) ||
                range > 5 &&
                GetDistance(target) > 5 &&
                !InLineOfSpellSightCheck(target))
            {
                return false;
            }
            return true;
        }

       public static bool AttackableNoCC(WoWUnit target, int range)
        {
            if (target == null ||
                !target.IsValid ||
                !target.Attackable ||
                !target.CanSelect ||
                !target.IsAlive ||
                //target.IsCritter ||
                //Blacklist.Contains(target.Guid, BlacklistFlags.All) ||
                target.Distance - target.CombatReach - 1 > range ||
                Invulnerable(target) ||
                !IsEnemy(target) ||
                range > 5 &&
                GetDistance(target) > 5 &&
                !InLineOfSpellSightCheck(target))
            {
                return false;
            }
            return true;
        }

       public static bool AttackableNoLoS(WoWUnit target, int range)
        {
            if (target == null ||
                !target.IsValid ||
                !target.Attackable ||
                !target.CanSelect ||
                !target.IsAlive ||
                //target.IsCritter ||
                //Blacklist.Contains(target.Guid, BlacklistFlags.All) ||
                GetDistance(target) > range ||
                Invulnerable(target) ||
                DebuffCCBreakonDamage(target) ||
                !IsEnemy(target))
            {
                return false;
            }
            return true;
        }

        private static bool AttackableNoCCLoS(WoWUnit target, int range)
        {
            if (target == null ||
                !target.IsValid ||
                !target.Attackable ||
                !target.CanSelect ||
                !target.IsAlive ||
                //target.IsCritter ||
                //Blacklist.Contains(target.Guid, BlacklistFlags.All) ||
                GetDistance(target) > range ||
                Invulnerable(target) ||
                !IsEnemy(target))
            {
                return false;
            }
            return true;
        }

        #endregion

        #region AuraCheck

        public static bool UnitHasAura(string auraName, WoWUnit target)
        {
            return target.GetAllAuras().Any(aura => aura.Name == auraName);
        }

        private static bool UnitHasAura(int auraID, WoWUnit target)
        {
            return target.GetAllAuras().Any(aura => aura.SpellId == auraID);
        }

        private static bool MeHasAura(string auraName)
        {
            return Me.GetAllAuras().Any(aura => aura.Name == auraName);
        }

        private static bool MeHasAura(int auraID)
        {
            return Me.GetAllAuras().Any(aura => aura.SpellId == auraID);
        }

        private static bool MyAura(string auraName, WoWUnit target)
        {
            return target.GetAllAuras().Any(aura => aura.Name == auraName && aura.CreatorGuid == Me.Guid);
        }


        private static bool MyAura(int auraID, WoWUnit target)
        {
            return target.GetAllAuras().Any(aura => aura.SpellId == auraID && aura.CreatorGuid == Me.Guid);
        }

        private static double MyAuraTimeLeft(string auraName, WoWUnit target)
        {
            return (from aura in target.GetAllAuras()
                    where aura.Name == auraName && aura.CreatorGuid == Me.Guid
                    select aura.TimeLeft.TotalMilliseconds).FirstOrDefault();
        }

        private static double MyAuraTimeLeft(int auraID, WoWUnit target)
        {
            return (from aura in target.GetAllAuras()
                    where aura.SpellId == auraID && aura.CreatorGuid == Me.Guid
                    select aura.TimeLeft.TotalMilliseconds).FirstOrDefault();
        }

        private static double MyAuraStackCount(string auraName, WoWUnit target)
        {
            return (from aura in target.GetAllAuras()
                    where aura.Name == auraName && aura.CreatorGuid == Me.Guid
                    select aura.StackCount).FirstOrDefault();
        }

        private static double MyAuraStackCount(int auraID, WoWUnit target)
        {
            return (from aura in target.GetAllAuras()
                    where aura.SpellId == auraID && aura.CreatorGuid == Me.Guid
                    select aura.StackCount).FirstOrDefault();
        }

        #endregion

        #region BasicCheck

        public static bool BasicCheck(WoWUnit target)
        {
            return target != null && target.IsValid && target.IsAlive;
        }

        #endregion

        #region  BattleStandard

        private static Composite UseBattleStandard()
        {
            return
                new Decorator(
                    ret =>
                    DayWalkerSettings.Instance.UseHealthstones &&
                    Me.Combat &&
                    Me.HealthPercent < DayWalkerSettings.Instance.HealthstoneHPPercent &&
                    Me.CurrentTarget != null &&
                    Me.CurrentTarget.CurrentHealth > Me.HealthPercent &&
                    Me.CurrentMap.IsBattleground,
                    new Action(delegate
                        {
                            if (Me.IsAlliance)
                            {
                                WoWItem bs = Me.BagItems.FirstOrDefault(o => o.Entry == 18606);
                                //18606 Alliance Battle Standard

                                if (!MeHasAura("Alliance Battle Standard") && bs != null &&
                                    bs.CooldownTimeLeft.TotalMilliseconds <= MyLatency)
                                {
                                    bs.Use();
                                    //Lua.DoString("RunMacroText(\"/5 Used Healthstone\")");
                                    //Lua.DoString("RunMacroText(\"/s Used Battle Standard\")");
                                    Logging.Write("Use Battle Standard at " +
                                                  Math.Round(Me.HealthPercent, 0) + "%");
                                }
                            }

                            if (Me.IsHorde)
                            {
                                WoWItem bs = Me.BagItems.FirstOrDefault(o => o.Entry == 18607);
                                //18606 Horde Battle Standard

                                if (!MeHasAura("Horde Battle Standard") && bs != null &&
                                    bs.CooldownTimeLeft.TotalMilliseconds <= MyLatency)
                                {
                                    bs.Use();
                                    //Lua.DoString("RunMacroText(\"/5 Used Healthstone\")");
                                    //Lua.DoString("RunMacroText(\"/s Used Battle Standard\")");
                                    Logging.Write("Use Battle Standard at " +
                                                  Math.Round(Me.HealthPercent, 0) + "%");
                                }
                            }

                            return RunStatus.Failure;
                        })
                    );
        }

        #endregion

        #region CanUseEquippedItem

        //Thank Apoc
        public static bool CanUseEquippedItem(WoWItem item)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                // Check for engineering tinkers!
                var itemSpell = Styx.WoWInternals.Lua.GetReturnVal<string>("return GetItemSpell(" + item.Entry + ")", 0);
                if (string.IsNullOrEmpty(itemSpell))
                    return false;
            }

            return item.Usable && item.Cooldown <= 0;
        }

        #endregion

        #region CastSpell

        private static WoWUnit LastCastUnit;
        private static DateTime LastCastTime = DateTime.Now;
        private static string LastCastSpell = "";
        private static string WriteReason;
        private static DateTime LastWriteLog;
     

        private static void CastSpell(string spellName, WoWUnit target, string reason = "")
        {
            if (spellName != "Freezing Trap" &&
                spellName != "Trap Launcher" 
               )
            {
                if (Me.IsCasting)
                {
                    SpellManager.StopCasting();
                }

               // if (DayWalkerSettings.Instance.WriteLog)
                {
                    Logging.Write("Skip " + spellName + " and Cast Freezing Trap");
                }
                return;
            }

            //Logging.Write(LogLevel.Diagnostic,
            //              "spellName: {0} - PowerCost: {1} - CastTime: {2} - spellCooldownBack: {3} - Now: {4}",
            //              PowerCost,
            //              CastTime, spellCooldownBack.ToString("ss:fff"), DateTime.Now.ToString("ss:fff"));

            SpellManager.Cast(spellName, target);

            LastCastTime = DateTime.Now;
            WriteReason = "";
            WriteReason = reason;
            LastCastSpell = spellName;
            LastCastUnit = target;

            if (!DayWalkerSettings.Instance.WriteLog || LastWriteLog > DateTime.Now) return;

            LastWriteLog = DateTime.Now + TimeSpan.FromMilliseconds(MyLatency);

            string barTwo = "mana: "  + Me.CurrentMana;


            Color colorlog;
            if (target == Me)
            {
                colorlog = Colors.GreenYellow;
            }

            else if (target == Me.CurrentTarget)
            {
                colorlog = Colors.Yellow;
            }
            else
            {
                colorlog = Colors.YellowGreen;
            }

            Logging.Write(colorlog, DateTime.Now.ToString("ss:fff") + " HP: " +
                                    Math.Round(Me.HealthPercent) + "% " + barTwo + " " +
                                    SafeName(target) + " " +
                                    Math.Round(target.Distance, 1) + "y " +
                                    Math.Round(target.HealthPercent) + "% hp " + spellName + " (" +
                                    WriteReason + ")");
        }

        #endregion


        #region CancelAura

        public static void CancelAura(string aura, WoWUnit target)
        {
            WoWAura a = target.GetAuraByName(aura);
            if (a != null && a.Cancellable)
                a.TryCancelAura();
        }

        public static void CancelAura(int aura, WoWUnit target)
        {
            WoWAura a = target.GetAuraById(aura);
            if (a != null && a.Cancellable)
                a.TryCancelAura();
        }

        #endregion

        #region ConstantFace

        //private static void ConstantFace(WoWUnit unit)
        //{
        //    if (!IsOverrideModeOn && !Me.IsSafelyFacing(unit))
        //    {
        //        WoWMovement.ConstantFace(unit.Guid);
        //    }
        //}

        #endregion

        #region CountDebuff

        //private static double CountDebuff(WoWUnit u)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (u == null || !u.IsValid || !u.IsAlive)
        //            return 0;

        //        int numberofDebuff =
        //            u.Debuffs.Values.Count(
        //                debuff =>
        //                (debuff.Spell.DispelType == WoWDispelType.Magic ||
        //                 debuff.Spell.DispelType == WoWDispelType.Poison ||
        //                 debuff.Spell.DispelType == WoWDispelType.Disease));

        //        return numberofDebuff;
        //    }
        //}

        private static double CountDebuffAll(WoWUnit u)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                int numberofDebuff =
                    u.Debuffs.Values.Count();

                return numberofDebuff;
            }
        }

        private static double CountDebuffMagic(WoWUnit u)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                int numberofDebuff =
                    u.Debuffs.Values.Count(
                        debuff =>
                        (debuff.Spell.DispelType == WoWDispelType.Magic));

                return numberofDebuff;
            }
        }

        //private static double CountDebuffRootandSnareMechanic(WoWUnit u)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (u == null || !u.IsValid || !u.IsAlive)
        //            return 0;

        //        return
        //            u.ActiveAuras.Values.Count(
        //                debuff =>
        //                (debuff.Spell.Mechanic == WoWSpellMechanic.Snared ||
        //                 debuff.Spell.Mechanic == WoWSpellMechanic.Rooted));
        //    }
        //}

        #endregion

        #region CountDPSTarget

        private static int CountDPSTarget(WoWUnit target)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (Me.CurrentMap.IsArena || Me.CurrentMap.IsBattleground)
                {
                    return NearbyUnFriendlyUnits.Count(
                        unit =>
                        unit.IsValid &&
                        unit.IsPlayer &&
                        unit.CurrentTarget != null &&
                        unit.CurrentTarget.IsValid &&
                        unit.CurrentTarget == target &&
                        (TalentSort(unit) >= 2 &&
                         TalentSort(unit) <= 3 &&
                         unit.Location.Distance(target.Location) < 40 ||
                         TalentSort(unit) == 1 &&
                         unit.Location.Distance(target.Location) < 15) &&
                        !DebuffCC(unit));
                }
                return NearbyUnFriendlyUnits.Count(
                    unit =>
                    unit.IsValid &&
                    unit.CurrentTarget != null &&
                    unit.CurrentTarget.IsValid &&
                    unit.CurrentTarget == target &&
                    !DebuffCC(unit));
            }
        }

        private static bool HasDPSTarget(WoWUnit target)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (Me.CurrentMap.IsArena || Me.CurrentMap.IsBattleground)
                {
                    return NearbyUnFriendlyUnits.Any(
                        unit =>
                        unit.IsValid &&
                        unit.IsPlayer &&
                        unit.CurrentTarget != null &&
                        unit.CurrentTarget.IsValid &&
                        unit.CurrentTarget == target &&
                        (TalentSort(unit) >= 2 &&
                         TalentSort(unit) <= 3 &&
                         unit.Location.Distance(target.Location) < 40 ||
                         TalentSort(unit) == 1 &&
                         unit.Location.Distance(target.Location) < 15) &&
                        !DebuffCC(unit));
                }
                return NearbyUnFriendlyUnits.Any(
                    unit =>
                    unit.IsValid &&
                    unit.CurrentTarget != null &&
                    unit.CurrentTarget.IsValid &&
                    unit.CurrentTarget == target &&
                    !DebuffCC(unit));
            }
        }

        #endregion

        #region CountMagicDPSTarget

        //private static int CountMagicDPSTarget(WoWUnit target)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (Me.CurrentMap.IsArena || Me.CurrentMap.IsBattleground)
        //        {
        //            return NearbyUnFriendlyUnits2().Count(
        //                unit =>
        //                unit.IsValid &&
        //                unit.IsPlayer &&
        //                unit.CurrentTarget != null &&
        //                unit.CurrentTarget.IsValid &&
        //                unit.CurrentTarget == target &&
        //                TalentSort(unit) == 3 &&
        //                unit.Location.Distance(target.Location) < 40 &&
        //                !DebuffCC(unit));
        //        }
        //        return NearbyUnFriendlyUnits2().Count(
        //            unit =>
        //            unit.IsValid &&
        //            unit.CurrentTarget != null &&
        //            unit.CurrentTarget.IsValid &&
        //            unit.CurrentTarget == target &&
        //            unit.PowerType == WoWPowerType.Mana &&
        //            unit.Location.Distance(target.Location) < 40 &&
        //            !DebuffCC(unit));
        //    }
        //}

        #endregion

        #region CountMeleeDPSTarget

        private static int CountMeleeDPSTarget(WoWUnit target)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (Me.CurrentMap.IsArena || Me.CurrentMap.IsBattleground)
                {
                    return NearbyUnFriendlyUnits.Count(
                        unit =>
                        unit.IsValid &&
                        unit.IsPlayer &&
                        unit.CurrentTarget != null &&
                        unit.CurrentTarget.IsValid &&
                        unit.CurrentTarget == target &&
                        TalentSort(unit) == 1 &&
                        unit.Location.Distance(target.Location) < 15 &&
                        !DebuffCC(unit));
                }
                return NearbyUnFriendlyUnits.Count(
                    unit =>
                    unit.IsValid &&
                    unit.CurrentTarget != null &&
                    unit.CurrentTarget.IsValid &&
                    unit.CurrentTarget == target &&
                    unit.Location.Distance(target.Location) < 15 &&
                    !DebuffCC(unit));
            }
        }

        #endregion

        #region CountPhysicDPSTarget

        //private static int CountPhysicDPSTarget(WoWUnit target)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (Me.CurrentMap.IsArena || Me.CurrentMap.IsBattleground)
        //        {
        //            return NearbyUnFriendlyUnits2().Count(
        //                unit =>
        //                unit.IsValid &&
        //                unit.IsPlayer &&
        //                unit.CurrentTarget != null &&
        //                unit.CurrentTarget.IsValid &&
        //                unit.CurrentTarget == target &&
        //                (TalentSort(unit) == 2 &&
        //                 unit.Location.Distance(target.Location) < 40 ||
        //                 TalentSort(unit) == 1 &&
        //                 unit.Location.Distance(target.Location) < 25) &&
        //                !DebuffCC(unit));
        //        }
        //        return NearbyUnFriendlyUnits2().Count(
        //            unit =>
        //            unit.IsValid &&
        //            unit.CurrentTarget != null &&
        //            unit.CurrentTarget.IsValid &&
        //            unit.CurrentTarget == target &&
        //            unit.Location.Distance(target.Location) < 15 &&
        //            !DebuffCC(unit));
        //    }
        //}

        #endregion

        #region CountEnemyNear

       public static double CountEnemyNear(WoWUnit unitCenter, float distance)
        {
            return FarUnFriendlyUnits.Where(BasicCheck).Count(
                unit =>
                (Me.CurrentMap.Name == "Proving Grounds" ||
                 IsDummy(unit) ||
                 unit.Combat &&
                 unit.MaxHealth > MeMaxHealth*0.2 &&
                 unit.GotTarget &&
                 FarFriendlyUnits.Contains(unit.CurrentTarget)) &&
                GetDistance(unitCenter, unit) <= distance);
        }

        public static bool HasEnemyNear(WoWUnit unitCenter, float distance)
        {
            return FarUnFriendlyUnits.Where(BasicCheck).Any(
                unit =>
                (Me.CurrentMap.Name == "Proving Grounds" ||
                 IsDummy(unit) ||
                 unit.Combat &&
                 unit.MaxHealth > MeMaxHealth*0.2 &&
                 unit.GotTarget &&
                 FarFriendlyUnits.Contains(unit.CurrentTarget)) &&
                GetDistance(unitCenter, unit) <= distance);
        }

        #endregion

        #region CountEnemyNearTarget

        public static int CountEnemyNearTarget(WoWUnit target)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                return NearbyUnFriendlyUnits.Count(
                    unit =>
                    unit.IsValid &&
                    unit.CurrentTarget != null &&
                    unit.CurrentTarget.IsValid &&
                    unit.CurrentTarget == target &&
                    !DebuffCC(unit));
            }
        }

        #endregion

        #region CountEnemyNearNoCC

        //private static double CountEnemyNearNoCC(WoWUnit unitCenter, float distance)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        return
        //            NearbyUnFriendlyUnits2().Where(
        //                unit =>
        //                unit.IsValid &&
        //                unitCenter.Location.Distance(unit.Location) <= distance &&
        //                (unit.Combat || !Me.IsInInstance && IsDummy(unit)) &&
        //                !unit.IsPet &&
        //                !DebuffCC(unit) &&
        //                (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember ||
        //                 !Me.IsInInstance && (unit.IsTargetingMeOrPet || IsDummy(unit)))).Aggregate
        //                <WoWUnit, double>(0, (current, unit) => current + 1);
        //    }
        //}

        #endregion

        #region CountEnemyPestilence

        //private static double CountEnemyDontHaveBloodPlagueorFrostFever(WoWUnit unitCenter, float distance)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        return
        //            NearbyUnFriendlyUnits2().Where(
        //                unit =>
        //                unit.IsValid &&
        //                unitCenter.Location.Distance(unit.Location) <= distance &&
        //                (unit.Combat || !Me.IsInInstance && IsDummy(unit)) &&
        //                !unit.IsPet &&
        //                (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember ||
        //                 !Me.IsInInstance && (unit.IsTargetingMeOrPet || IsDummy(unit))) &&
        //                !Invulnerable(unit) &&
        //                (!MyAura("Frost Fever", unit) ||
        //                 !MyAura("Blood Plague", unit))).Aggregate
        //                <WoWUnit, double>(0, (current, unit) => current + 1);
        //    }
        //}

        #endregion

        #region CountEnemyFromPoint

        //private static double CountEnemyFromPoint(WoWPoint pointCenter, float radius)
        //{
        //    return
        //        NearbyUnFriendlyUnits2().Where(
        //            unit =>
        //            pointCenter.Distance(unit.Location) <= radius &&
        //            unit.Combat).Aggregate
        //            <WoWUnit, double>(0, (current, unit) => current + 1);
        //}

        #endregion

        #region CountEneyTargettingUnit

        //private static double CountEneyTargettingUnit(WoWUnit target, float distance)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        return
        //            NearbyUnFriendlyUnits2().Where(
        //                unit =>
        //                unit.IsValid &&
        //                GetMinDistance(unit) < distance &&
        //                unit.CurrentTarget != null &&
        //                unit.CurrentTarget.IsValid &&
        //                unit.Level <= target.Level + 3 &&
        //                //unit.Combat && 
        //                !unit.IsPet &&
        //                unit.CurrentTarget == target //&&
        //                //DebuffCC(unit) <= MyLatency
        //                ).Aggregate
        //                <WoWUnit, double>(0, (current, unit) => current + 1);
        //    }
        //}

        #endregion

        #region HasEnemyNearGotCCBreakonDamge

        private static bool HasEnemyNearGotCCBreakonDamge(WoWUnit unitCenter, float distance)
        {
            if (!BasicCheck(unitCenter))
            {
                return false;
            }

            return FarUnFriendlyPlayers.Any(
                unit =>
                BasicCheck(unit) &&
                GetDistance(unitCenter, unit) <= distance &&
                //unitCenter.Location.Distance(unit.Location) <= distance &&
                DebuffCCBreakonDamage(unit));
        }


        //private static double CountEnemyNearNoCCBreakonDamge(WoWUnit unitCenter, float distance)
        //{
        //    if (unitCenter == null || !unitCenter.IsValid)
        //    {
        //        return 0;
        //    }
        //    return
        //        NearbyUnFriendlyUnits.Where(
        //            unit =>
        //            unit.IsValid &&
        //            unitCenter.Location.Distance(unit.Location) <= distance &&
        //            DebuffCCBreakonDamage(unit)).Aggregate
        //            <WoWUnit, double>(0, (current, unit) => current + 1);
        //}

        #endregion

        #region CurrentTargetCheck

        private static WoWUnit CurrentTargetCheckLast;
        private static double CurrentTargetCheckDist;
        private static bool CurrentTargetCheckDebuffCCBreakonDamage;
        private static bool CurrentTargetCheckInvulnerable;
        private static bool CurrentTargetCheckInvulnerablePhysic;
        private static bool CurrentTargetCheckInvulnerableMagic;
        private static bool CurrentTargetCheckIsEnemy;
        private static bool CurrentTargetCheckInLineOfSpellSight;
        private static bool CurrentTargetCheckFacing;
        private static DateTime CurrentTargetCheckLastTime;

        private static void CurrentTargetCheck()
        {
            if (CurrentTargetCheckLastTime > DateTime.Now)
            {
                return;
            }

            CurrentTargetCheckLastTime = DateTime.Now + CurrentTargetCheckTimeOut;

            //CurrentTargetCheckLast = null;
            //CurrentTargetCheckDist = 1000;
            //CurrentTargetCheckDebuffCCBreakonDamage = false;
            //CurrentTargetCheckInvulnerable = false;
            //CurrentTargetCheckIsEnemy = false;
            //CurrentTargetCheckInLineOfSpellSight = false;
            //CurrentTargetCheckFacing = false;

            if (!BasicCheck(Me.CurrentTarget))
            {
                return;
            }

            CurrentTargetCheckLast = Me.CurrentTarget;
            CurrentTargetCheckFacing = Me.IsSafelyFacing(Me.CurrentTarget, 220);
            CurrentTargetCheckDist = GetDistance(Me.CurrentTarget);

            CurrentTargetCheckIsEnemy = IsEnemy(Me.CurrentTarget);
            if (!CurrentTargetCheckIsEnemy)
            {
                return;
            }

            CurrentTargetCheckInvulnerable = Invulnerable(Me.CurrentTarget);
            if (CurrentTargetCheckInvulnerable)
            {
                return;
            }

            CurrentTargetCheckDebuffCCBreakonDamage = DebuffCCBreakonDamage(Me.CurrentTarget);
            if (CurrentTargetCheckDebuffCCBreakonDamage)
            {
                return;
            }

            CurrentTargetCheckInvulnerableMagic = InvulnerableSpell(Me.CurrentTarget);
            CurrentTargetCheckInvulnerablePhysic = InvulnerablePhysic(Me.CurrentTarget);

            if (CurrentTargetCheckDist <= 5)
            {
                CurrentTargetCheckInLineOfSpellSight = true;
            }
            else if (InLineOfSpellSightCheck(Me.CurrentTarget))
            {
                CurrentTargetCheckInLineOfSpellSight = true;
            }
        }

       public static bool CurrentTargetAttackable(double distance,
                                                    bool includeCurrentTargetCheckInvulnerableePhysic = false,
                                                    bool includeCurrentTargetCheckInvulnerableeMagic = false)
        {
            if (Me.CurrentTarget == null ||
                !Me.CurrentTarget.IsValid ||
                !Me.CurrentTarget.Attackable ||
                !Me.CurrentTarget.IsAlive) // ||
                //Blacklist.Contains(Me.CurrentTarget.Guid, BlacklistFlags.All))
            {
                return false;
            }

            if (Me.CurrentTarget != CurrentTargetCheckLast)
            {
                CurrentTargetCheck();
            }

            if (!CurrentTargetCheckIsEnemy ||
                CurrentTargetCheckDebuffCCBreakonDamage ||
                CurrentTargetCheckInvulnerable ||
                !CurrentTargetCheckFacing && !DayWalkerSettings.Instance.AutoFace  ||
                includeCurrentTargetCheckInvulnerableePhysic && CurrentTargetCheckInvulnerablePhysic ||
                includeCurrentTargetCheckInvulnerableeMagic && CurrentTargetCheckInvulnerableMagic ||
                CurrentTargetCheckDist > distance ||
                !CurrentTargetCheckInLineOfSpellSight)
            {
                return false;
            }
            return true;
        }

        public static bool CurrentTargetAttackableNoLoS(double distance)
        {
            if (Me.CurrentTarget == null ||
                !Me.CurrentTarget.IsValid ||
                !Me.CurrentTarget.Attackable ||
                !Me.CurrentTarget.IsAlive) // ||
                //Blacklist.Contains(Me.CurrentTarget.Guid, BlacklistFlags.All))
            {
                return false;
            }

            if (Me.CurrentTarget != CurrentTargetCheckLast)
            {
                CurrentTargetCheck();
            }

            if (CurrentTargetCheckDebuffCCBreakonDamage ||
                CurrentTargetCheckInvulnerable ||
                !CurrentTargetCheckIsEnemy ||
                CurrentTargetCheckDist > distance)
            {
                return false;
            }
            return true;
        }

        #endregion

        #region DeathRotation

        private const int RezMaxMobsNear = 0;
        private const int RezWaitTime = 10;
        private const int RezWaitDist = 20;

        private static string SelfRezSpell { get; set; }
        private static double MobsNearby { get; set; }
        private static DateTime NextSuppressMessage = DateTime.MinValue;

        private static Composite DeathRotation()
        {
            return new Decorator(
                req =>
                    {
                        if (Me.IsAlive || Me.IsGhost)
                            return false;

                        List<string> hasSoulstone = Styx.WoWInternals.Lua.GetReturnValues("return HasSoulstone()",
                                                                        "hawker.lua");
                        if (hasSoulstone == null || hasSoulstone.Count == 0 ||
                            String.IsNullOrEmpty(hasSoulstone[0]) ||
                            hasSoulstone[0].ToLower() == "nil")
                            return false;

                        if (!DayWalkerSettings.Instance.AutoMove)
                        {
                            if (NextSuppressMessage < DateTime.Now)
                            {
                                NextSuppressMessage = DateTime.Now.AddSeconds(RezWaitTime);
                                Logging.Write(
                                    "Suppressing {0} behavior since movement disabled...",
                                    hasSoulstone[0]);
                            }
                            return false;
                        }

                        SelfRezSpell = hasSoulstone[0];
                        return true;
                    },
                new Sequence(
                    new Action(
                        r =>
                        Logging.Write("Waiting up to {0} seconds for clear area to use {1}...",
                                      RezWaitTime, SelfRezSpell)),
                    new Wait(
                        RezWaitTime,
                        until =>
                            {
                                MobsNearby = CountEnemyNear(Me, RezWaitDist);
                                return MobsNearby <= RezMaxMobsNear || Me.IsAlive || Me.IsGhost;
                            },
                        new Action(r =>
                            {
                                if (Me.IsGhost)
                                {
                                    Logging.Write(
                                        "Insignia taken or corpse release by something other than Singular...");
                                    return RunStatus.Failure;
                                }

                                if (Me.IsAlive)
                                {
                                    Logging.Write("Ressurected by something other than Singular...");
                                    return RunStatus.Failure;
                                }

                                return RunStatus.Success;
                            })
                        ),
                    new DecoratorContinue(
                        req => MobsNearby > RezMaxMobsNear,
                        new Action(r =>
                            {
                                Logging.Write("Still {0} enemies within {1} yds, skipping {2}",
                                              MobsNearby, RezWaitDist, SelfRezSpell);
                                return RunStatus.Failure;
                            })
                        ),
                    new Action(
                        r =>
                        Logging.Write("Ressurrecting Singular by invoking {0}...", SelfRezSpell)),
                    new Action(r => Styx.WoWInternals.Lua.DoString("UseSoulstone()")),
                    new WaitContinue(1, until => Me.IsAlive || Me.IsGhost, new ActionAlwaysSucceed())
                    )
                );
        }

        #endregion

        #region Dismount

        private static Composite Dismount()
        {
            return new Decorator(
                ret =>
                IsUsingAFKBot &&
                (Me.Combat || Me.CurrentMap.IsBattleground) &&
                Me.Mounted &&
                !Me.IsFlying &&
                !IsMoving(Me) &&
                HasEnemyNear(Me, 30),
                new Action(delegate
                    {
                        Mount.Dismount("Stuck on mount? Dismounting for combat.");
                        return RunStatus.Failure;
                    }));
        }

        #endregion

        #region FacingOverride

        private static bool FacingOverride(WoWUnit unit)
        {
            if (!BasicCheck(unit))
            {
                return false;
            }

            if (Me.IsSafelyFacing(unit, 180) ||
                Me.IsMoving && Me.IsSafelyFacing(unit, 220) ||
                DayWalkerSettings.Instance.AutoFace 
                ) // &&
                //(CurrentBotBase == "Questing" ||
                // CurrentBotBase == "Grind Bot"))
            {
                return true;
            }

            return false;
            //}
        }

        #endregion

        #region FacingOverrideWide

        private static bool FacingOverrideWide(WoWUnit unit)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (unit == null)
                {
                    return false;
                }

                if (Me.IsSafelyFacing(unit, 220))
                {
                    return true;
                }

                if (
                    DayWalkerSettings.Instance.AutoFace &&
                    (CurrentBotBase == "Questing" ||
                     CurrentBotBase == "Grind Bot"))
                {
                    return true;
                }

                return false;
            }
        }

        #endregion

        #region FindFirstUsableItemBySpell

        /// <summary>
        ///  Checks for items in the bag, and returns the first item that has an usable spell from the specified string array.
        /// </summary>
        /// <param name="spellNames"> Array of spell names to be check.</param>
        /// <returns></returns>
        private static WoWItem FindFirstUsableItemBySpell(params string[] spellNames)
        {
            List<WoWItem> carried = StyxWoW.Me.CarriedItems;
            // Yes, this is a bit of a hack. But the cost of creating an object each call, is negated by the speed of the Contains from a hash set.
            // So take your optimization bitching elsewhere.
            var spellNameHashes = new HashSet<string>(spellNames);

            return (from i in carried
                    let spells = i.ItemSpells
                    where i.ItemInfo != null && spells != null && spells.Count != 0 &&
                          i.Usable &&
                          i.Cooldown <= 0 &&
                          i.ItemInfo.RequiredLevel <= StyxWoW.Me.Level &&
                          spells.Any(
                              s => s.IsValid && s.ActualSpell != null && spellNameHashes.Contains(s.ActualSpell.Name))
                    orderby i.ItemInfo.Level descending
                    select i).FirstOrDefault();
        }

        #endregion

        #region FindGround

        private static WoWPoint FindGround(WoWPoint Point, int HoverZ)
        {
            if (!Me.CurrentMap.IsArena || !Me.CurrentMap.IsBattleground)
            {
                return Point;
            }

            var PointHover = new WoWPoint(Point.X, Point.Y, Point.Z + HoverZ);
            var CalculatedPoint = new WoWPoint(Point.X, Point.Y, PointHover.Z - HeightOffTheGround(PointHover, HoverZ));

            //Logging.Write("Point X: {0} - Y: {1} - Z: {2}", Point.X, Point.Y, Point.Z);
            //Logging.Write("CalculatedPoint X: {0} - Y: {1} - Z: {2}", CalculatedPoint.X, CalculatedPoint.Y,
            //              CalculatedPoint.Z);

            return CalculatedPoint;
        }

        #endregion

        #region GetAsyncKeyState

        [DllImport("user32.dll")]
        private static extern short GetAsyncKeyState(Keys vKey);

        #endregion

        #region GetCurrentSpec

        internal static string GetCurrentSpec()
        {
            if (Me.Specialization == WoWSpec.HunterBeastMastery)
            {
                return "BeastMastery";
            }
            if (Me.Specialization == WoWSpec.HunterMarksmanship)
            {
                return "Marksmanship";
            }
            if (Me.Specialization == WoWSpec.HunterSurvival)
            {
                return "Survival";
            }
            Logging.Write("No Specialization detected");
            return "No Specialization detected";
        }

        #endregion

        #region GetUnitAuras

       
     

    
   
       
   

        #endregion

        #region GetAllMyAuras

        //private static DateTime _lastGetAllMyAuras = DateTime.Now;

        //private static void DumpAuras()
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (_lastGetAllMyAuras.AddSeconds(10) < DateTime.Now)
        //        {
        //            int i = 1;
        //            Logging.Write(LogLevel.Diagnostic, "----------------------------------");
        //            foreach (WoWAura aura in Me.GetAllAuras())
        //            {
        //                Logging.Write(LogLevel.Diagnostic,
        //                              i + ". Me.GetAllAuras Name: " + aura.Name + " - SpellId: " + aura.SpellId);
        //                i = i + 1;
        //            }
        //            Logging.Write(LogLevel.Diagnostic, "----------------------------------");

        //            i = 1;
        //            Logging.Write(LogLevel.Diagnostic, "----------------------------------");
        //            foreach (var aura in Me.Auras)
        //            {
        //                Logging.Write(LogLevel.Diagnostic,
        //                              i + ". Me.Auras - Name: " + aura.Value.Name + " - SpellId: " + aura.Value.SpellId);
        //                i = i + 1;
        //            }
        //            Logging.Write(LogLevel.Diagnostic, "----------------------------------");

        //            i = 1;
        //            Logging.Write(LogLevel.Diagnostic, "----------------------------------");
        //            foreach (var aura in Me.ActiveAuras)
        //            {
        //                Logging.Write(LogLevel.Diagnostic,
        //                              i + ". Me.ActiveAuras - Name: " + aura.Value.Name + " - SpellId: " +
        //                              aura.Value.SpellId);
        //                i = i + 1;
        //            }
        //            Logging.Write(LogLevel.Diagnostic, "----------------------------------");

        //            i = 1;
        //            Logging.Write(LogLevel.Diagnostic, "----------------------------------");
        //            foreach (var aura in Me.PassiveAuras)
        //            {
        //                Logging.Write(LogLevel.Diagnostic,
        //                              i + ". Me.PassiveAuras - Name: " + aura.Value.Name + " - SpellId: " +
        //                              aura.Value.SpellId);
        //                i = i + 1;
        //            }
        //            Logging.Write(LogLevel.Diagnostic, "----------------------------------");

        //            _lastGetAllMyAuras = DateTime.Now;
        //        }
        //    }
        //}

        #endregion

        #region GetDistance

        public static float GetDistance(WoWUnit target)
        {
            if (target == null ||
                !target.IsValid)
            {
                return 10000;
            }

            if (target.CombatReach < 3)
            {
                return (float) target.Distance;
            }

            return (float) target.Distance - target.CombatReach + 1;
        }

        public static float GetDistance(WoWUnit source, WoWUnit target)
        {
            if (source == null ||
                !source.IsValid ||
                target == null ||
                !target.IsValid)
            {
                return 10000;
            }

            if (target.CombatReach < 3)
            {
                return source.Location.Distance(target.Location);
            }

            return source.Location.Distance(target.Location) - target.CombatReach + 1;
        }

        #endregion

        #region GetBestTarget

        public static WoWUnit UnitBestTarget;

        public static bool GetBestTarget()
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                UnitBestTarget = null;
                if (Me.CurrentMap.IsBattleground || Me.CurrentMap.IsArena)
                {
                    UnitBestTarget = NearbyUnFriendlyPlayers.OrderBy(unit => unit.CurrentHealth).FirstOrDefault(
                        unit => unit != null && unit.IsValid &&
                                Attackable(unit, 40));

                    if (UnitBestTarget == null)
                    {
                        UnitBestTarget = NearbyUnFriendlyPlayers.OrderBy(unit => unit.Distance).FirstOrDefault(
                            unit => unit != null && unit.IsValid &&
                                    Attackable(unit, 80));
                    }
                }

                if (UnitBestTarget == null && !Me.CurrentMap.IsBattleground && !Me.CurrentMap.IsArena)
                {
                    UnitBestTarget = NearbyUnFriendlyUnits.OrderBy(unit => unit.ThreatInfo.RawPercent).FirstOrDefault(
                        unit => unit != null && unit.IsValid &&
                                (Me.CurrentMap.Name == "Proving Grounds" ||
                                 Me.IsFacing(unit) &&
                                 (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember ||
                                  unit.IsTargetingMeOrPet)) &&
                                Attackable(unit, 40));
                }
                return UnitBestTarget != null;
            }
        }
        private static IEnumerable<WoWUnit> GetAllUnits()
        {
            return ObjectManager.GetObjectsOfType<WoWUnit>(true, true);
        }

        private static readonly List<WoWUnit> NearbyFriendlyPlayers = new List<WoWUnit>();
        private static readonly List<WoWUnit> NearbyFriendlyUnits = new List<WoWUnit>();
        private static readonly List<WoWUnit> FarFriendlyPlayers = new List<WoWUnit>();
        private static readonly List<WoWUnit> FarFriendlyUnits = new List<WoWUnit>();
        private static readonly List<WoWUnit> NearbyUnFriendlyPlayers = new List<WoWUnit>();
        private static readonly List<WoWUnit> NearbyUnFriendlyUnits = new List<WoWUnit>();
        private static readonly List<WoWUnit> FarUnFriendlyPlayers = new List<WoWUnit>(); //Don't use in this CC
       public static readonly List<WoWUnit> FarUnFriendlyUnits = new List<WoWUnit>();

        private static Composite GetUnits()
        {
            return new Action(delegate
            {
                EnemyListCacheClear();
                FriendListCacheClear();

                NearbyFriendlyPlayers.Clear();
                NearbyFriendlyUnits.Clear();
                FarFriendlyPlayers.Clear();
                FarFriendlyUnits.Clear();
                NearbyUnFriendlyPlayers.Clear();
                NearbyUnFriendlyUnits.Clear();
                FarUnFriendlyPlayers.Clear();
                FarUnFriendlyUnits.Clear();

                foreach (
                    var unit in
                        GetAllUnits()
                            .Where(
                                unit =>
                                unit.CanSelect &&
                                unit.IsAlive &&
                                GetDistance(unit) <= DayWalkerSettings.Instance.SearchRange &&
                                !Blacklist.Contains(unit.Guid, BlacklistFlags.All)))
                {
                    if (IsMyPartyRaidMember(unit))
                    {
                        var player = unit as WoWPlayer;
                        if (player != null || NeedHealUnit(unit))
                        {
                            FarFriendlyPlayers.Add(unit);
                            FarFriendlyUnits.Add(unit);
                            if (unit.Distance <= 40)
                            {
                                NearbyFriendlyUnits.Add(unit);
                                NearbyFriendlyPlayers.Add(unit);
                            }
                        }
                        else
                        {
                            FarFriendlyUnits.Add(unit);
                            if (unit.Distance <= 40)
                            {
                                NearbyFriendlyUnits.Add(unit);
                            }
                        }
                    }
                    else if (IsEnemy(unit))
                    {
                        var player = unit as WoWPlayer;
                        if (player != null)
                        {
                            FarUnFriendlyPlayers.Add(unit);
                            FarUnFriendlyUnits.Add(unit);
                            if (unit.Distance <= 40)
                            {
                                NearbyUnFriendlyUnits.Add(unit);
                                NearbyUnFriendlyPlayers.Add(unit);
                            }
                        }
                        else
                        {
                            FarUnFriendlyUnits.Add(unit);
                            if (unit.Distance <= 40)
                            {
                                NearbyUnFriendlyUnits.Add(unit);
                            }
                        }
                    }
                }
                return RunStatus.Failure;
            });
        }

        #endregion

        #region GetBestFocus

        private static WoWUnit UnitBestFocus;

        private static bool GetBestFocus()
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                UnitBestFocus = null;

                UnitBestFocus = NearbyUnFriendlyPlayers.OrderByDescending(TalentSort)
                                                       .ThenByDescending(unit => unit.HealthPercent)
                                                       .FirstOrDefault(
                                                           unit => unit != null && unit.IsValid &&
                                                                   Me.CurrentTarget != null &&
                                                                   unit != Me.CurrentTarget &&
                                                                   AttackableNoLoS(unit, 40));
                return UnitBestFocus != null;
            }
        }

        #endregion

        #region GetUnitHealerAround

        private static WoWUnit UnitHealerAround;

        private static bool GetUnitHealerAround()
        {
            UnitHealerAround = null;
            //using (StyxWoW.Memory.AcquireFrame())
            {
                UnitHealerAround = NearbyUnFriendlyPlayers.FirstOrDefault(
                    unit => unit != null && unit.IsValid &&
                            TalentSort(unit) == 4);

                return UnitHealerAround != null;
            }
        }

        #endregion

        #region GlobalCheck

        private static DateTime GlobalCheckTime;
        private static TimeSpan CurrentTargetCheckTimeOut;

        private static void GlobalCheck()
        {
            if (GlobalCheckTime > DateTime.Now) return;

            GlobalCheckTime = DateTime.Now + TimeSpan.FromSeconds(30);

            UpdateMyLatency();

            UpdateEventHandler();

            if (Me.CurrentMap.IsRaid)
            {
                //AuraCacheExpire = TimeSpan.FromMilliseconds(500);
                CurrentTargetCheckTimeOut = TimeSpan.FromMilliseconds(500);
            }
            else if (Me.CurrentMap.IsArena || Me.CurrentMap.IsBattleground)
            {
                //AuraCacheExpire = TimeSpan.FromMilliseconds(50);
                CurrentTargetCheckTimeOut = TimeSpan.FromMilliseconds(50);
            }
            else
            {
                //AuraCacheExpire = TimeSpan.FromMilliseconds(100);
                CurrentTargetCheckTimeOut = TimeSpan.FromMilliseconds(100);
            }
        }

        #endregion

        #region HealWeight

        private static double HealWeight(WoWUnit target)
        {
            if (!BasicCheck(target))
            {
                return 1000;
            }

            if (!target.Combat)
            {
                return target.HealthPercent;
            }

            var targetValue = 0;

            if (Me.CurrentMap.IsArena || Me.CurrentMap.IsBattleground)
            {
                foreach (
                    var unit in
                        FarUnFriendlyPlayers.Where(
                            unit => BasicCheck(unit) && unit.Combat && unit.CurrentTarget == target))
                {
                    if (TalentSort(unit) < 4 && BuffBurst(unit))
                    {
                        targetValue = targetValue + 5;
                    }
                    else
                    {
                        targetValue = targetValue + 3;
                    }
                }
            }
            else
            {
                //targetValue = 0;
                foreach (var unit in
                    FarUnFriendlyUnits.Where(
                        unit =>
                        BasicCheck(unit) &&
                        unit.Combat &&
                        unit.CurrentTarget == target))
                {
                    if (unit.IsBoss)
                    {
                        targetValue = targetValue + 5;
                    }
                    else
                    {
                        targetValue = targetValue + 1;
                    }
                }
            }

            return target.HealthPercent - targetValue;
        }

        #endregion

        #region HeightOffTheGround;

        /// <summary>
        /// calculate a unit's vertical distance (height) above ground level (mesh).  this is the units position
        /// relative to the ground and is independent of any other character.  
        /// </summary>
        /// <param name="u">unit</param>
        /// <returns>float.MinValue if can't determine, otherwise distance off ground</returns>
        private static float HeightOffTheGround(WoWPoint Point, int HoverZ)
        {
            var listMeshZ = Navigator.FindHeights(Point.X, Point.Y).Where(h => h <= Point.Z);
            if (listMeshZ.Any())
            {
                return Point.Z - listMeshZ.Max();
            }
            return HoverZ;
        }

        #endregion

        #region IndexToKeys

        public static Keys KeyTwo;

        private static Keys IndexToKeys(int index)
        {
            switch (index)
            {
                case 1:
                    return Keys.A;
                case 2:
                    return Keys.B;
                case 3:
                    return Keys.C;
                case 4:
                    return Keys.D;
                case 5:
                    return Keys.E;
                case 6:
                    return Keys.F;
                case 7:
                    return Keys.G;
                case 8:
                    return Keys.H;
                case 9:
                    return Keys.I;
                case 10:
                    return Keys.J;
                case 11:
                    return Keys.K;
                case 12:
                    return Keys.L;
                case 13:
                    return Keys.M;
                case 14:
                    return Keys.N;
                case 15:
                    return Keys.O;
                case 16:
                    return Keys.P;
                case 17:
                    return Keys.Q;
                case 18:
                    return Keys.R;
                case 19:
                    return Keys.S;
                case 20:
                    return Keys.T;
                case 21:
                    return Keys.U;
                case 22:
                    return Keys.V;
                case 23:
                    return Keys.W;
                case 24:
                    return Keys.X;
                case 25:
                    return Keys.Y;
                case 26:
                    return Keys.Z;
                case 27:
                    return Keys.D1;
                case 28:
                    return Keys.D2;
                case 29:
                    return Keys.D3;
                case 30:
                    return Keys.D4;
                case 31:
                    return Keys.D5;
                case 32:
                    return Keys.D6;
                case 33:
                    return Keys.D7;
                case 34:
                    return Keys.D8;
                case 35:
                    return Keys.D9;
                case 36:
                    return Keys.D0;
                case 37:
                    return Keys.Up;
                case 38:
                    return Keys.Down;
                case 39:
                    return Keys.Left;
                case 40:
                    return Keys.Right;
                case 41:
                    return Keys.NumPad1;
                case 42:
                    return Keys.NumPad2;
                case 43:
                    return Keys.NumPad3;
                case 44:
                    return Keys.NumPad4;
                case 45:
                    return Keys.NumPad5;
                case 46:
                    return Keys.NumPad6;
                case 47:
                    return Keys.NumPad7;
                case 48:
                    return Keys.NumPad8;
                case 49:
                    return Keys.NumPad9;
                case 50:
                    return Keys.NumPad0;
            }
            return Keys.None;
        }

        internal static Keys IndexToKeysMod(int index)
        {
            switch (index)
            {
                case 1:
                    return Keys.LShiftKey;
                case 2:
                    return Keys.LControlKey;
                case 3:
                    return Keys.LMenu;
            }
            return Keys.None;
        }

        #endregion

        #region IsAttacking

        //private static bool IsAttacking()
        //{
        //    return Me.IsCasting && Me.CastingSpell.Name == "Denounce";
        //}

        #endregion

        #region IsDummy

        public static bool IsDummy(WoWUnit target)
        {
            if (!BasicCheck(target))
            {
                return false;
            }
            return target.Entry == 31146 || // Raider's
                   target.Entry == 67127 || // Shine Training Dummy
                   target.Entry == 46647 || // 81-85
                   target.Entry == 32546 || // Ebon Knight's (DK)
                   target.Entry == 31144 || // 79-80
                   target.Entry == 32543 || // Veteran's (Eastern Plaguelands)
                   target.Entry == 32667 || // 70
                   target.Entry == 32542 || // 65 EPL
                   target.Entry == 32666 || // 60
                   target.Entry == 30527; // ?? Boss one (no idea?)
        }

        #endregion

        #region IsEnemy

        //private static WoWUnit MyPartyorRaidUnit;

       public static bool IsMyPartyRaidMember(WoWUnit target)
        {
            if (FriendListCache.ContainsKey(target.Guid))
            {
                return true;
            }

            if (EnemyListCache.ContainsKey(target.Guid))
            {
                return false;
            }

            if (NeedHealUnit(target))
            {
                FriendListCacheAdd(target);
                return true;
            }

            if (target.IsPlayer)
            {
                var player = target as WoWPlayer;
                if (player != null && (player == Me || player.IsInMyPartyOrRaid))
                {
                    FriendListCacheAdd(target);
                    return true;
                }
            }
            else
            {
                var player = target.CreatedByUnit as WoWPlayer;
                if (player != null && (player == Me || player.IsInMyPartyOrRaid))
                {
                    FriendListCacheAdd(target);
                    return true;
                }
            }

            return false;
        }

       public static bool IsEnemy(WoWUnit target)
        {
            if (EnemyListCache.ContainsKey(target.Guid))
            {
                //Logging.Write("{0} in EnemyListCache, Skip Check!", target.Name);
                return true;
            }

            if (FriendListCache.ContainsKey(target.Guid))
            {
                //Logging.Write("{0} in FriendListCache, Skip Check!", target.Name);
                return false;
            }


            if (IsMyPartyRaidMember(target))
            {
                if (UnitHasAura("Reshape Life", target) || //Reshape Life
                    UnitHasAura("Convert", target)) //Convert
                {
                    return true;
                }

                FriendListCacheAdd(target);
                //Logging.Write("{0} in IsMyPartyRaidMember, Skip Check!", target.Name);
                return false;
            }

            if (!target.IsFriendly && target.Attackable && !target.IsQuestGiver)
            {
                EnemyListCacheAdd(target);
                //Logging.Write("{0} !target.IsFriendly && target.Attackable, Skip Check!", target.Name);
                return true;
            }

            if (Me.Combat && IsDummy(target) && Me.IsFacing(target))
            {
                EnemyListCacheAdd(target);
                //Logging.Write("{0} IsDummy(target) && Me.Combat && Me.IsFacing(target), Skip Check!", target.Name);
                return true;
            }

            return false;
        }

        #endregion

        #region IsMoving

        public static bool IsMoving(WoWUnit target)
        {
            return target.MovementInfo.MovingBackward ||
                   target.MovementInfo.MovingForward ||
                   target.MovementInfo.MovingStrafeLeft ||
                   target.MovementInfo.MovingStrafeRight;
        }

        #endregion

        #region IsUnitsInLosOfEachOther

        //private static bool IsUnitsInLosOfEachOtherAtFeet(WoWUnit unitSource, WoWUnit unitDestination)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        return (GameWorld.IsInLineOfSpellSight(
        //            unitSource.Location,
        //            unitDestination.Location));
        //    }
        //}

        //private static bool IsUnitsInLosOfEachOtherAtWaist(WoWUnit unitSource, WoWUnit unitDestination)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        return (GameWorld.IsInLineOfSpellSight(
        //            unitSource.Location.Add(0.0f, 0.0f, unitSource.BoundingHeight/2),
        //            unitDestination.Location.Add(0.0f, 0.0f, unitDestination.BoundingHeight/2)));
        //    }
        //}

        //private static bool IsUnitsInLosOfEachOtherAtChest(WoWUnit unitSource, WoWUnit unitDestination)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        return (GameWorld.IsInLineOfSpellSight(
        //            unitSource.Location.Add(0.0f, 0.0f, unitSource.BoundingHeight*0.75f),
        //            unitDestination.Location.Add(0.0f, 0.0f, unitDestination.BoundingHeight*0.75f)));
        //    }
        //}

        //private static bool IsUnitsInLosOfEachOtherAtHead(WoWUnit unitSource, WoWUnit unitDestination)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        return (GameWorld.IsInLineOfSpellSight(
        //            unitSource.Location.Add(0.0f, 0.0f, unitSource.BoundingHeight),
        //            unitDestination.Location.Add(0.0f, 0.0f, unitDestination.BoundingHeight)));
        //    }
        //}

        #endregion

        #region IsUsingCooldown

        private static int CountMySummonUnit()
        {
            var TotalMySummonUnit =
                FarFriendlyUnits.Count(
                    unit =>
                    BasicCheck(unit) &&
                    unit.CreatedByUnit == Me &&
                    unit.MaxHealth > Me.MaxHealth*0.5);

            //var TotalMySummonUnit = FarFriendlyUnits.Where(unit => unit.CreatedByUnit == Me).ToList();

            //if (TotalMySummonUnit > 1)
            //{
            //    foreach (var woWUnit in FarFriendlyUnits.Where(unit => unit.CreatedByUnit == Me && unit.MaxHealth > Me.MaxHealth * 0.5))
            //    {
            //        Logging.Write(woWUnit.Name);
            //    }
            //}

            return TotalMySummonUnit;
        }

        private static bool IsUsingCooldown()
        {
            //"Rapid Fire" 3045
            if (MeHasAura(3045) || MeHasAura("The Beast Within") || CountMySummonUnit() > 3)
            {
                return true;
            }
            return false;
        }

        #endregion

        #region NeedHealUnit

        private static readonly HashSet<uint> NeedHealUnitHS = new HashSet<uint>
            {
                62442, //Tsulong
                71404, //Wrathion <The Black Prince> 
                71166, //Wrathion <The Black Prince> 
                71165, //Wrathion <The Black Prince>
                71357, //Wrathion <The Black Prince>
                72218, //Oto the Protector
                72219, //Ki the Assassin
                72221, //Kavan the Arcanist
                72220, //Sooli the Survivalist
                71828, //Sikari the Mistweaver
                71604, //Contaminated Puddle
                71604, //Immerseus blobs
                71995, //Leven Dawnblade
                71996, //Rook Stonetoe
                71480, //Sun Tenderheart
            };

        private static bool NeedHealUnit(WoWUnit target)
        {
            return NeedHealUnitHS.Contains(target.Entry) &&
                   target.IsFriendly;
        }

        #endregion

        #region UnitAuraTimeLeft

        //private static double UnitAuraTimeLeft(string auraName, WoWUnit u)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (u == null || !u.IsValid || !u.IsAlive)
        //            return 0;

        //        WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.Name == auraName && a.CreatorGuid == u.Guid);

        //        if (aura == null)
        //        {
        //            return 0;
        //        }
        //        return aura.TimeLeft.TotalMilliseconds;
        //    }
        //}

        //private static double UnitAuraTimeLeft(int auraID, WoWUnit u)
        //{
        //   //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (u == null)
        //            return 0;

        //        WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.SpellId == auraID && a.CreatorGuid == u.Guid);

        //        if (aura == null)
        //        {
        //            return 0;
        //        }
        //        return aura.TimeLeft.TotalMilliseconds;
        //    }
        //}

        #endregion

        #region SafelyFacingTarget

       public static void SafelyFacingTarget(WoWUnit target)
        {
            if (!BasicCheck(target))
            {
                return;
            }

            if (DayWalkerSettings.Instance.AutoFace &&  !Me.IsSafelyFacing(target))
            {
                Me.SetFacing(target.Location);
            }
        }

        #endregion

        #region SafeName

        private static string SafeName(WoWUnit unit)
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (unit == null || !unit.IsValid)
                {
                    return "null or invalid";
                }
                if (unit == Me)
                {
                    return "Myself";
                }
                if (unit.IsPlayer)
                {
                    return unit.Class.ToString();
                }
                if (unit.IsPet)
                {
                    return unit.CreatureType.ToString();
                }
            }
            return unit.Name;
        }

        #endregion

        #region SetAutoAttack

        private static DateTime SetAutoAttackLast;

        private static Composite SetAutoAttack()
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                return new Action(delegate
                    {
                        if (Me.CurrentTarget != null &&
                            SetAutoAttackLast < DateTime.Now &&
                            Me.CurrentTarget.IsValid &&
                            Me.CurrentTarget.IsAlive &&
                            !CurrentTargetAttackable(50))
                        {
                            //Logging.Write("Stop Attack");
                            Styx.WoWInternals.Lua.DoString("RunMacroText('/stopattack');");
                            SetAutoAttackLast = DateTime.Now + TimeSpan.FromMilliseconds(2000);
                            return RunStatus.Failure;
                        }

                        //Disable this, it conflic with the targeting system
                        //if (THSettings.Instance.AutoAttack &&
                        //    CurrentTargetAttackable(50) &&
                        //    !Me.Mounted &&
                        //    !Me.IsAutoAttacking &&
                        //    !MeHasAura("Camouflage"))
                        //{
                        //    SpellManager.Cast("Auto Attack");
                        //    return RunStatus.Failure;
                        //}
                        return RunStatus.Failure;
                    });
            }
        }

        #endregion

        #region Spells

        private static double GetSpellCastTime(string spell)
        {
            SpellFindResults results;
            if (SpellManager.FindSpell(spell, out results))
            {
                return results.Override != null ? results.Override.CastTime/1000.0 : results.Original.CastTime/1000.0;
            }
            return 99999.9;
        }

        private static double GetSpellCastTime(int spell)
        {
            SpellFindResults results;
            if (SpellManager.FindSpell(spell, out results))
            {
                return results.Override != null ? results.Override.CastTime/1000.0 : results.Original.CastTime/1000.0;
            }
            return 99999.9;
        }

        private static double GetSpellPowerCost(string spell)
        {
            SpellFindResults results;
            if (SpellManager.FindSpell(spell, out results))
            {
                return results.Override != null ? results.Override.PowerCost : results.Original.PowerCost;
            }
            return 99999.9;
        }

        private static double GetSpellPowerCost(int spell)
        {
            SpellFindResults results;
            if (SpellManager.FindSpell(spell, out results))
            {
                return results.Override != null ? results.Override.PowerCost : results.Original.PowerCost;
            }
            return 99999.9;
        }

        private static TimeSpan GetSpellCooldown(string spell)
        {
            //return SpellManager.Spells[spell].CooldownTimeLeft;

            SpellFindResults results;
            if (SpellManager.FindSpell(spell, out results))
            {
                return results.Override != null ? results.Override.CooldownTimeLeft : results.Original.CooldownTimeLeft;
            }
            return TimeSpan.FromMilliseconds(0);
            //return TimeSpan.MaxValue;
        }

        private static TimeSpan GetSpellCooldown(int spell)
        {
            SpellFindResults results;
            if (SpellManager.FindSpell(spell, out results))
            {
                return results.Override != null ? results.Override.CooldownTimeLeft : results.Original.CooldownTimeLeft;
            }
            return TimeSpan.FromMilliseconds(0);
            //return TimeSpan.MaxValue;
        }

        private static bool SpellOnCooldown(string spell)
        {
            SpellFindResults results;
            if (SpellManager.FindSpell(spell, out results))
            {
                return results.Override != null ? results.Override.Cooldown : results.Original.Cooldown;
            }

            return false;
        }

        private static bool SpellOnCooldown(int spell)
        {
            SpellFindResults results;
            if (SpellManager.FindSpell(spell, out results))
            {
                return results.Override != null ? results.Override.Cooldown : results.Original.Cooldown;
            }

            return false;
        }

        private static WoWSpell SpellFind(string spell)
        {
            SpellFindResults results;
            if (SpellManager.FindSpell(spell, out results))
            {
                return results.Override ?? results.Original;
            }

            return null;
        }

        #endregion Spells

    

        #region TalentSort

        private static byte TalentSort(WoWUnit target)
        {
            if (target == null || !target.IsValid)
            {
                return 0;
            }

            switch (target.Class)
            {
                case WoWClass.DeathKnight:
                    return 1;
                case WoWClass.Druid:
                    if (target.MaxMana < target.MaxHealth/2)
                        return 1;
                    if (UnitHasAura(106735, target)) //Restoration Overrides Passive
                        return 4;
                    return 3;
                case WoWClass.Hunter:
                    return 2;
                case WoWClass.Mage:
                    return 3;
                case WoWClass.Monk:
                    if (UnitHasAura(115070, target)) //Stance of the Wise Serpent
                        return 4;
                    return 1;
                case WoWClass.Paladin:
                    if (target.MaxMana > target.MaxHealth/2)
                        return 4;
                    return 1;
                case WoWClass.Priest:
                    if (UnitHasAura(114884, target)) //Vampiric Touch <DND>
                        return 3;
                    return 4;
                case WoWClass.Rogue:
                    return 1;
                case WoWClass.Shaman:
                    if (target.MaxMana < target.MaxHealth/2)
                        return 1;
                    if (UnitHasAura(16213, target)) //Purification
                        return 4;
                    return 3;
                case WoWClass.Warlock:
                    return 3;
                case WoWClass.Warrior:
                    return 1;
            }
            return 0;
        }

        private static byte TalentSortSimple(WoWUnit target)
        {
            byte sortSimple = TalentSort(target);

            if (sortSimple == 4)
            {
                return 4;
            }

            if (sortSimple < 4 && sortSimple > 0)
            {
                return 1;
            }

            return 0;
        }

        private static string TalentSortRole(WoWUnit target)
        {
            switch (TalentSort(target))
            {
                case 1:
                    return "Melee";
                case 2:
                    return "Range DPS";
                case 3:
                    return "Range DPS";
                case 4:
                    return "Healer";
            }
            return "Unknow";
        }

        #endregion

        #region TalentValue

        private static int TalentValue(int blood, int frost, int unholy)
        {
            return GetCurrentSpec() == "Blood" ? blood : (GetCurrentSpec() == "Unholy" ? unholy : frost);
        }

        private static bool TalentValue(bool blood, bool frost, bool unholy)
        {
            return GetCurrentSpec() == "Blood" ? blood : (GetCurrentSpec() == "Unholy" ? unholy : frost);
        }

        #endregion

        #region UpdateStatusEvent

        private static void UpdateStatusEvent(object sender, LuaEventArgs args)
        {
            DayWalkerSettings.Instance.UpdateStatus = true;
        }

        #endregion

        #region OnBotStartedEvent

        private static void OnBotStartedEvent(object o)
        {
            if (Me.Inventory.Equipped.Hands != null &&
                Me.Inventory.Equipped.Hands.Name.Contains("Malevolent Gladiator's Scaled Gauntlets"))
            {
            }
            Logging.Write("----------------------------------");
            Logging.Write("Update Status on Bot Start");
            Logging.Write("----------------------------------");

            DayWalkerSettings.Instance.Pause = false;
            DayWalkerSettings.Instance.UpdateStatus = true;
        }

        #endregion

        #region UpdateEventHandler

        private static void UpdateEventHandler()
        {
            //Logging.Write(LogLevel.Diagnostic, "UpdateEventHandler");

            if (IsUsingAFKBot &&
                !Me.CurrentMap.IsArena &&
                !Me.CurrentMap.IsBattleground &&
                !Me.CurrentMap.IsDungeon &&
                !Me.CurrentMap.IsRaid &&
                !EventHandlers.CombatLogAttached)
            {
                EventHandlers.AttachCombatLogEvent();
                //Logging.Write(LogLevel.Diagnostic, "AttachCombatLogEvent");
            }

            if ((!IsUsingAFKBot ||
                 Me.CurrentMap.IsArena ||
                 Me.CurrentMap.IsBattleground ||
                 Me.CurrentMap.IsDungeon ||
                 Me.CurrentMap.IsRaid) &&
                EventHandlers.CombatLogAttached)
            {
                EventHandlers.DetachCombatLogEvent();
                //Logging.Write(LogLevel.Diagnostic, "AttachCombatLogEvent");
            }
        }

        #endregion

        #region UpdateMyLatency

        private static double MyLatency;

        private static void UpdateMyLatency()
        {
            MyLatency = (StyxWoW.WoWClient.Latency);

            //Use here because Lag Tolerance cap at 400
            //Logging.Write("----------------------------------");
            //Logging.Write("MyLatency: " + MyLatency);
            //Logging.Write("----------------------------------");

            if (MyLatency > 400)
            {
                //Lag Tolerance cap at 400
                MyLatency = 400;
            }

            //Logging.Write(LogLevel.Diagnostic, "My Current Latency = {0}", MyLatency);
        }

        #endregion

        #region UpdateMyTalent

        private static string _hasTalent = "";

        private static void UpdateMyTalentEvent(object sender, LuaEventArgs args)
        {
            UpdateMyTalent();
        }

        private static void UpdateMyTalent()
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                _hasTalent = "";
                for (int i = 1; i <= 18; i++)
                {
                    _hasTalent = _hasTalent +
                                 Styx.WoWInternals.Lua.GetReturnVal<String>(
                                     string.Format(
                                         "local t= select(5,GetTalentInfo({0})) if t == true then return '['..select(1,GetTalentInfo({0}))..'] ' end return nil",
                                         i), 0);
                }

                Logging.Write("----------------------------------");
                Logging.Write("Talent:");
                Logging.Write(_hasTalent);
                Logging.Write("----------------------------------");
                _hasTalent = "";
            }
        }

        #endregion

        #region UseHealthstone

        private static Composite UseHealthstone()
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                return
                    new Decorator(
                        ret =>
                        DayWalkerSettings.Instance.UseHealthstones &&
                        Me.Combat &&
                        Me.HealthPercent < DayWalkerSettings.Instance.HealthstoneHPPercent &&
                        Me.CurrentTarget != null &&
                        Me.CurrentTarget.CurrentHealth > Me.HealthPercent,
                        new Action(delegate
                            {
                                WoWItem hs = Me.BagItems.FirstOrDefault(o => o.Entry == 5512);
                                //5512 Healthstone
                                if (hs != null && hs.CooldownTimeLeft.TotalMilliseconds <= MyLatency)
                                {
                                    hs.Use();
                                    //Lua.DoString("RunMacroText(\"/s Used Healthstone\")");
                                    Logging.Write("Use Healthstone at " + Math.Round(Me.HealthPercent, 0) +
                                                  "%");
                                }
                                return RunStatus.Failure;
                            })
                        );
            }
        }

        #endregion
    

        #region UpdateMyGlyph

        private static void UpdateMyGlyphEvent(object sender, LuaEventArgs args)
        {
            UpdateMyGlyph();
        }

        //private static readonly HashSet<string> NoGCDSpells = new HashSet<string> { };
        private static string HasGlyph;
        private static string HasGlyphName;

        private static void UpdateMyGlyph()
        {
            HasGlyph = "";
            HasGlyphName = "";
            //using (StyxWoW.Memory.AcquireFrame())
            {
                var glyphCount = Styx.WoWInternals.Lua.GetReturnVal<int>("return GetNumGlyphSockets()", 0);

                if (glyphCount != 0)
                {
                    for (int i = 1; i <= glyphCount; i++)
                    {
                        string lua =
                            String.Format(
                                "local enabled, glyphType, glyphTooltipIndex, glyphSpellID, icon = GetGlyphSocketInfo({0});if (enabled) then return glyphSpellID else return 0 end",
                                i);

                        var glyphSpellId = Styx.WoWInternals.Lua.GetReturnVal<int>(lua, 0);

                        try
                        {
                            if (glyphSpellId > 0)
                            {
                                HasGlyphName = HasGlyphName + "[" + (WoWSpell.FromId(glyphSpellId)) + " - " +
                                               glyphSpellId +
                                               "] ";
                                HasGlyph = HasGlyph + "[" + glyphSpellId + "] ";
                            }
                            else
                            {
                                Logging.Write("Glyphdetection - No Glyph in slot " + i);
                                //TreeRoot.Stop();
                            }
                        }
                        catch (Exception ex)
                        {
                            Logging.Write("We couldn't detect your Glyphs");
                            Logging.Write("Report this message to us: " + ex);
                            //TreeRoot.Stop();
                        }
                    }
                }

                Logging.Write("----------------------------------");
                Logging.Write("Glyph:");
                Logging.Write(HasGlyphName);
                Logging.Write("----------------------------------");
            }
        }

        #endregion

        #region UpdateRaidPartyMembers

        //private static IEnumerable<WoWPartyMember> GroupMembers
        //{
        //    get { return !Me.GroupInfo.IsMe.CurrentMap.IsRaid ? Me.GroupInfo.PartyMembers : Me.GroupInfo.RaidMembers; }
        //}

        //private static void UpdateRaidPartyMembersEvent(object sender, LuaEventArgs args)
        //{
        //    UpdateRaidPartyMembers();
        //}

        //private static DateTime UpdateRaidPartyMembersLast;

        //private static Composite UpdateRaidPartyMembersComp()
        //{
        //    return new Decorator(
        //        ret =>
        //        UpdateRaidPartyMembersLast + TimeSpan.FromSeconds(60) < DateTime.Now ||
        //        UpdateRaidPartyMembersLast + TimeSpan.FromSeconds(10) < DateTime.Now &&
        //        !Me.Combat ||
        //        MeHasAura("Arena Preparation") ||
        //        MeHasAura("Preparation"),
        //        new Action(delegate
        //            {
        //                UpdateRaidPartyMembers();
        //                UpdateRaidPartyMembersLast = DateTime.Now;
        //                return RunStatus.Failure;
        //            }));
        //}

        //private static readonly List<WoWPlayer> RaidPartyMembers = new List<WoWPlayer>();

        //private static void UpdateRaidPartyMembers()
        //{
        //    //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        EnemyListCache.Clear();
        //        RaidPartyMembers.Clear();

        //        foreach (var woWPartyMember in GroupMembers)
        //        {
        //            if (woWPartyMember.ToPlayer() != null)
        //            {
        //                //Logging.Write("Add " + woWPartyMember.ToPlayer().Class + " to RaidPartyMembers");
        //                RaidPartyMembers.Add(woWPartyMember.ToPlayer());
        //            }
        //        }

        //        if (!RaidPartyMembers.Contains(Me))
        //        {
        //            RaidPartyMembers.Add(Me);
        //        }
        //    }
        //}

        #endregion

        #region UpdateStatus

        public static int UseSpecialization;
        private static string CurrentBotBase;
        public static bool IsUsingAFKBot;
        private static double MeMaxHealth;
        private static ulong MeGuid;

        public static void UpdateStatus()
        {
            //using (StyxWoW.Memory.AcquireFrame())
            {
                if (DayWalkerSettings.Instance.UpdateStatus)
                    if (Me.IsValid)
                    {
                        {
                            CurrentBotBase = TreeRoot.Current.Name;
                          


                            Logging.Write("----------------------------------");
                            Logging.Write("Building Rotation base on current Talents and Glyphs......");
                            Logging.Write("----------------------------------");
                            Logging.Write("");

                            //if (!FriendListCache.ContainsKey(Me.Guid))
                            //{
                            //    FriendListCacheAdd(Me, 86400);
                            //}

                            UpdateEventHandler();

                            UpdateMyTalent();

                            UpdateMyGlyph();

                          

                            if (Me.Specialization == WoWSpec.WarlockDestruction)
                            {
                                UseSpecialization = 3;
                            }
                            else if (Me.Specialization == WoWSpec.WarlockAffliction)
                            {
                                UseSpecialization = 2;
                            }
                            else
                            {
                                UseSpecialization = 1;
                            }

                            Logging.Write("----------------------------------");
                            Logging.Write("Hold 1 second Control + " + IndexToKeys(DayWalkerSettings.Instance.PauseKey) +
                                          " To Toggle Pause Mode.");
                            Logging.Write("----------------------------------");
                            Logging.Write("");

                            if (TreeRoot.Current.Name == "Questing" ||
                                TreeRoot.Current.Name == "[BETA] Grindbuddy" ||
                                TreeRoot.Current.Name == "ArcheologyBuddy" ||
                                TreeRoot.Current.Name == "Auto Angler" ||
                                TreeRoot.Current.Name == "Gatherbuddy2" ||
                                TreeRoot.Current.Name == "Grind Bot" ||
                                TreeRoot.Current.Name == "BGBuddy" ||
                                TreeRoot.Current.Name == "DungeonBuddy" ||
                                TreeRoot.Current.Name == "Mixed Mode")
                            {
                                IsUsingAFKBot = true;
                            }
                            else
                            {
                                IsUsingAFKBot = false;
                            }

                            MeGuid = Me.Guid;
                            MeMaxHealth = Me.MaxHealth;


                            if (DayWalkerSettings.Instance.BurstKey > 7)
                            {
                                Logging.Write("----------------------------------");
                                Logging.Write("Hold 1 second + " + IndexToKeys(DayWalkerSettings.Instance.BurstKey - 7) +
                                              " To Toggle Burst Mode");
                                Logging.Write("----------------------------------");
                                Logging.Write("");
                            }


                            Logging.Write("----------------------------------");
                            Logging.Write("Building Rotation Completed");
                            Logging.Write("----------------------------------");
                            Logging.Write("");

                            DayWalkerSettings.Instance.UpdateStatus = false;

                            
                        }
                    }
            }
        }

        #endregion
        #region RestRotation

        public static Composite RestRotation()
        {
            return new Decorator(
                ret =>
                DayWalkerSettings.Instance.UseFood &&
                Me.HealthPercent <= DayWalkerSettings.Instance.UseFoodHP &&
                !Me.Combat &&
                !Me.IsDead &&
                !Me.IsGhost &&
                DayWalkerSettings.Instance.AutoMove &&
                !Me.IsCasting &&
                !Me.IsSwimming &&
                !MeHasAura("Food") &&
                Styx.CommonBot.Inventory.Consumable.GetBestFood(true) != null,
                new Action(delegate
                {
                    Logging.Write("Using Food");
                    if (IsMoving(Me))
                    {
                        WoWMovement.MoveStop();
                        //StyxWoW.SleepForLagDuration();
                    }
                    Styx.CommonBot.Rest.FeedImmediate();
                    //new Wait(TimeSpan.FromMilliseconds(1000), ret => false,
                    //         new ActionAlwaysSucceed());
                    if (MeHasAura("Food") &&
                        Me.HealthPercent <
                        DayWalkerSettings.Instance.DoNotHealAbove &&
                        !Me.Combat)
                    {
                        return RunStatus.Running;
                    }
                    return RunStatus.Success;
                })
                );
        }
        #endregion
        #region ValidUnit

        //private static bool ValidUnit(WoWUnit u)
        //{
        //    //using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        if (u != null &&
        //            u.IsValid &&
        //            u.Attackable &&
        //            u.CanSelect &&
        //            u.IsAlive &&
        //            !u.IsDead &&
        //            !u.IsCritter &&
        //            !Blacklist.Contains(u.Guid, BlacklistFlags.All))
        //        {
        //            return true;
        //        }

        //        return false;
        //    }
        //}

        #endregion

        #region WriteTime

        private static DateTime WriteTimeDebug;

        private static void WriteTimeStart()
        {
            WriteTimeDebug = DateTime.Now;
        }

        private static void WriteTimeEnd(string Text = "WriteTime")
        {
            Logging.Write("{0} ms - {1}", Math.Round((DateTime.Now - WriteTimeDebug).TotalMilliseconds, 1), Text);
            WriteTimeDebug = DateTime.Now;
        }

        private static Composite WriteTimeStartComp()
        {
            return new Action(delegate
                {
                    WriteTimeDebug = DateTime.Now;
                    return RunStatus.Failure;
                });
        }

        private static Composite WriteTimeEndComp(string Text = "WriteTime")
        {
            return new Action(delegate
                {
                    Logging.Write("{0} ms - {1}", Math.Round((DateTime.Now - WriteTimeDebug).TotalMilliseconds, 1), Text);
                    WriteTimeDebug = DateTime.Now;
                    return RunStatus.Failure;
                });
        }

        #endregion
    }
}